
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BPainter>
#include <BStyle>
#include <BFont>
#include <BLabel>

#include <BHtmlItem>
#include "member_BHtmlItem.h"
#include "member_BXmlNode.h"
#include "member_BHtmlWidget.h"

using namespace BWE;

#define member					(*(member_BHtmlItem*)_ptr)
#define member_allocate()		_ptr = new member_BHtmlItem(this)
#define member_release()		delete (member_BHtmlItem*)_ptr

BHtmlItem::BHtmlItem(BHtmlItem* parent)
{
	member_allocate();
	if (parent)
		parent->addChild(this);
}
BHtmlItem::BHtmlItem(const BString& name, BHtmlItem* parent)
{
	member_allocate();
	if (name.contain(' '))
	{
		XmlFilter filter(name);
		this->setName(filter.name);
		for (auto it = filter.attribMap.begin(); it.valid(); ++it)
		{
			this->setAttrib(it.key(), it.value());
		}
	}
	else
	{
		this->setName(name);
	}
	if (parent)
		parent->addChild(this);
}
BHtmlItem::BHtmlItem(BXmlNode* node, BHtmlItem* parent)
{
	member_allocate();
	this->setName(node->name());
	this->setText(node->text());
	this->setFormat(node->format());
	xml_member(this)->attribMap = xml_member(node)->attribMap;
	for (int i = 0; i < node->childCount(); i++)
	{
		BXmlNode* childNode = node->child(i);
		if (childNode->name() == "!--")
			continue;
		BHtmlItem* child = new BHtmlItem(childNode);
		this->addChild(child);
	}
	member.dirtyHtml();
	if (parent)
		parent->addChild(this);
}
BHtmlItem::~BHtmlItem()
{
	member_release();
}

void BHtmlItem::copy(const BXmlNode* other)
{
	BXmlNode::copy(other);
	member.resetCells();
}
BXmlNode* BHtmlItem::clone() const
{
	BHtmlItem* item = new BHtmlItem();
	item->copy(this);
	return item;
}

bool BHtmlItem::setName(const BString& name)
{
	if (BObject::setName(name))
	{
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::setText(const BString& text)
{
	if (BXmlNode::setText(text))
	{
		member.resetCells();
		member.dirtyHtml();
		return true;
	}
	return false;
}

bool BHtmlItem::setAttrib(const BString& name, const BString& value)
{
	if (BXmlNode::setAttrib(name, value))
	{
		member.image = 0;
		member.dirtyHtml();
		return true;
	}
	return false;
}
void BHtmlItem::setAttribMap(const BMap<BString, BString>& attribMap)
{
	BXmlNode::setAttribMap(attribMap);
	member.dirtyHtml();
}
bool BHtmlItem::removeAttrib(const BString& name)
{
	if (BXmlNode::removeAttrib(name))
	{
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::clearAttribs()
{
	if (BXmlNode::clearAttribs())
	{
		member.dirtyHtml();
		return true;
	}
	return false;
}

BHtmlItem::Display BHtmlItem::display() const
{
	return member.display;
}

void BHtmlItem::setSelected(bool selected)
{
	if (member.html)
	{
		if (member.html->selectedItem() == this)
			member.html->setItemSelected(0);
		else
			member.html->setItemSelected(this);
	}
}
bool BHtmlItem::selected() const
{
	return member.selected;
}

BRange BHtmlItem::selectedRange() const
{
	return BRange(member.inputIndex, member.inputIndex + member.inputCount);
}
BString BHtmlItem::selectedText() const
{
	BString result;
	member.selection(result);
	return result;
}

BHtmlWidget* BHtmlItem::htmlWidget()
{
	return member.html;
}
const BHtmlWidget* BHtmlItem::htmlWidget() const
{
	return member.html;
}

BHtmlItem* BHtmlItem::parent()
{
	return dynamic_cast<BHtmlItem*>(BXmlNode::parent());
}
const BHtmlItem* BHtmlItem::parent() const
{
	return dynamic_cast<const BHtmlItem*>(BXmlNode::parent());
}

BHtmlItem* BHtmlItem::parent(const BString& name)
{
	return dynamic_cast<BHtmlItem*>(BXmlNode::parent(name));
}
const BHtmlItem* BHtmlItem::parent(const BString& name) const
{
	return dynamic_cast<const BHtmlItem*>(BXmlNode::parent(name));
}

BHtmlItem* BHtmlItem::addText(const BString& text)
{
	BHtmlItem* item = new BHtmlItem();
	item->setText(text);
	addChild(item);
	return item;
}
bool BHtmlItem::addChild(BHtmlItem* item)
{
	if (!item)
		return false;
	if (this == item)
		return false;
	if (BXmlNode::addChild(item))
	{
		item_member(item)->attach(member.html);
		member.dirtyHtml();
	}
	return true;
}
BHtmlItem* BHtmlItem::addChild(const BString& name)
{
	BHtmlItem* item = new BHtmlItem(name);
	addChild(item);
	return item;
}

BHtmlItem* BHtmlItem::insertText(int pos, const BString& text)
{
	BHtmlItem* item = new BHtmlItem();
	item->setText(text);
	insertChild(pos, item);
	return item;
}
bool BHtmlItem::insertChild(int pos, BHtmlItem* item)
{
	if (BXmlNode::insertChild(pos, item))
	{
		item_member(item)->html = member.html;
		member.dirtyHtml();
		return true;
	}
	return false;
}
BHtmlItem* BHtmlItem::insertChild(int pos, const BString& name)
{
	BHtmlItemHolder item = new BHtmlItem(name);
	if (insertChild(0, item))
		return item;
	return 0;
}

bool BHtmlItem::removeChild(int pos)
{
	if (BHtmlItem* item = this->child(pos))
	{
		item_member(item)->detach(member.html);
		BXmlNode::removeChild(item);
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::removeChild(const BString& name)
{
	if (BHtmlItem* item = this->child(name))
	{
		item_member(item)->detach(member.html);
		BXmlNode::removeChild(item);
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::removeChild(const BHtmlItem* item)
{
	if (BXmlNode::contain(item))
	{
		item_member(item)->detach(member.html);
		BXmlNode::removeChild(item);
		member.dirtyHtml();
		return true;
	}
	return false;
}

BHtmlItem* BHtmlItem::child(int index)
{
	BXmlNode* node = BXmlNode::child(index);
	return dynamic_cast<BHtmlItem*>(node);
}
const BHtmlItem* BHtmlItem::child(int index) const
{
	const BXmlNode* node = BXmlNode::child(index);
	return dynamic_cast<const BHtmlItem*>(node);
}

BHtmlItem* BHtmlItem::child(const BString& desc)
{
	BXmlNode* node = BXmlNode::child(desc);
	return dynamic_cast<BHtmlItem*>(node);
}
const BHtmlItem* BHtmlItem::child(const BString& desc) const
{
	const BXmlNode* node = BXmlNode::child(desc);
	return dynamic_cast<const BHtmlItem*>(node);
}

bool BHtmlItem::clearChildren()
{
	if (int count = this->childCount())
	{
		for (int i = 0; i < count; i++)
		{
			BXmlNode* child = this->child(i);
			if (BHtmlItem* item = dynamic_cast<BHtmlItem*>(child))
			{
				item->setSelected(false);
				item_member(item)->detach(member.html);
			}
		}
		BXmlNode::clearChildren();
		member.dirtyHtml();
		return true;
	}
	return false;
}

BRect BHtmlItem::area() const
{
	if (member.html)
		return member.area + member.html->offset();
	return member.area;
}
BRect BHtmlItem::rect() const
{
	if (member.html)
		return member.rect + member.html->offset();
	return member.rect;
}
const BFont* BHtmlItem::font() const
{
	return member.realFont;
}

int BHtmlItem::cellCount() const
{
	return member.cells.size();
}
BRect BHtmlItem::cellRect(int index) const
{
	if (member.html && member.cells.check(index))
		return member.cells[index].rect + member.html->offset();
	return member.cells(index).rect;
}
